package ar.edu.uba.fi.jmit.aspecter.monitor.fieldValue;

import java.util.Date;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import ar.edu.uba.fi.jmit.aspecter.AspecterTestCase;
import ar.edu.uba.fi.jmit.aspecter.core.Constants;
import ar.edu.uba.fi.jmit.aspecter.core.ResourceProperties;
import ar.edu.uba.fi.jmit.aspecter.core.interceptor.FieldAccessInterceptor;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.EventPriorityMock;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MockEvent;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.SenderFactoryMock;

public class FieldValueFieldAccessInterceptorTestCase extends AspecterTestCase {
	
	@Override
	protected void setUp() throws Exception {
		SenderFactoryMock.clean();
	}

	public void test() throws NotFoundException {
		try {
			String className = getNextClassName();
			FieldAccessInterceptor interceptor = new FieldValueFieldAccessInterceptor(className, "x", "monitor_FieldValueFieldAccessInterceptorTestCase", "id");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest10", className);
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object point = clazz.newInstance();
			clazz.getMethod("setId",new Class<?>[]{int.class}).invoke(point, 20);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("setY",new Class<?>[]{int.class}).invoke(point, 10);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("getY").invoke(point);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("setX",new Class<?>[]{int.class}).invoke(point, 10);
			assertEquals(1, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("getX").invoke(point);
			assertEquals(1, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			
			MockEvent event = SenderFactoryMock.getSenderInstance().getSendedEvents().get(0);
			assertEquals("monitor_FieldValueFieldAccessInterceptorTestCase", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
			assertSimilarDates(new Date(), (Date) event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE)));
			assertEquals(point.toString(), event.getSource());
			assertEquals(EventPriorityMock.NORMAL, event.getPriority());
			assertEquals(10, event.getData().get(ResourceProperties.getProperty(Constants.FIELD_NEW_VALUE)));
			assertEquals(20, event.getData().get(ResourceProperties.getProperty(Constants.EVENT_ID_OBJECT_KEY)));
			
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testIdInteger() throws NotFoundException {
		try {
			String className = getNextClassName();
			FieldAccessInterceptor interceptor = new FieldValueFieldAccessInterceptor(className, "x", "monitor_FieldValueFieldAccessInterceptorTestCase", "idInteger");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest10", className);
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object point = clazz.newInstance();
			clazz.getMethod("setIdInteger",new Class<?>[]{Integer.class}).invoke(point, new Integer(20));
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("setY",new Class<?>[]{int.class}).invoke(point, 10);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("getY").invoke(point);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("setX",new Class<?>[]{int.class}).invoke(point, 10);
			assertEquals(1, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("getX").invoke(point);
			assertEquals(1, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			
			MockEvent event = SenderFactoryMock.getSenderInstance().getSendedEvents().get(0);
			assertEquals("monitor_FieldValueFieldAccessInterceptorTestCase", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
			assertSimilarDates(new Date(), (Date) event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE)));
			assertEquals(point.toString(), event.getSource());
			assertEquals(EventPriorityMock.NORMAL, event.getPriority());
			assertEquals(10, event.getData().get(ResourceProperties.getProperty(Constants.FIELD_NEW_VALUE)));
			assertEquals(20, event.getData().get(ResourceProperties.getProperty(Constants.EVENT_ID_OBJECT_KEY)));
			
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testPublicMethod() {
		try {
			String className = getNextClassName();
			FieldAccessInterceptor interceptor = new FieldValueFieldAccessInterceptor("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest11", "publicField", "testPublicMethod", "getId()");
			CtClass ctClass = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest10", className);
			ctClass.instrument(interceptor);
			Class<?> clazz = ctClass.toClass();
			Object point = clazz.newInstance();
			clazz.getMethod("setId",new Class<?>[]{int.class}).invoke(point, 20);
			assertEquals(0, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			clazz.getMethod("invokePoint11",new Class<?>[]{int.class, int.class}).invoke(point, 1, 2);
			assertEquals(1, SenderFactoryMock.getSenderInstance().getSendedEvents().size());
			
			MockEvent event = SenderFactoryMock.getSenderInstance().getSendedEvents().get(0);
			assertEquals("testPublicMethod", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
			Date eventDate = (Date) event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE));
			assertSimilarDates(new Date(), eventDate);
			assertEquals(point.toString(), event.getSource());
			assertEquals(EventPriorityMock.NORMAL, event.getPriority());
			assertEquals(2, event.getData().get(ResourceProperties.getProperty(Constants.FIELD_NEW_VALUE)));
			assertEquals(1, event.getData().get(ResourceProperties.getProperty(Constants.EVENT_ID_OBJECT_KEY)));
			
		} catch (Exception e) {
			fail(e);
		}
	}
}
